package com.gibs.peixunapi.utils;

import com.gibs.peixunapi.model.BaseModel;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author liangjiawei
 * @date 2020/03/18/11:18
 * @Version 1.0
 * @Description:
 */
public class ConverterUtil {
	/**
	 *
	 * 自定义忽略队列，把source复制到target并且忽略你制定的属性
	 *
	 * @param source
	 * @param target
	 */
	public static void copyProperties(Object source, Object target,String... ignoreProperties) {
		BeanUtils.copyProperties(source, target, ignoreProperties);
	}
	/**
	 * 将source中不为空的字段取出加入忽略队列，把source复制到target并且忽略不为空的字段（复制空的字段）
	 *
	 * @param source
	 *            数据源
	 * @param target
	 *            目标
	 */
	public static void copyNullProperties(Object source, Object target) {
		BeanUtils.copyProperties(source, target, getNoNullProperties(source));
	}

	/**
	 *
	 * 将source中为null的字段取出加入忽略队列，把source复制到target并且忽略为null的字段（复制不为null的字段）
	 * 
	 * @param source
	 * @param target
	 */
	public static void copyNotNullProperties(Object source, Object target) {
		BeanUtils.copyProperties(source, target, getNullProperties(source));
	}

	/**
	 *
	 * 将source中不为null的字段取出加入忽略队列，把source复制到target并且忽略不为null的字段
	 * 
	 * @param source
	 * @param target
	 */
	public static void copyBlankProperties(Object source, Object target) {
		BeanUtils.copyProperties(source, target, getNotBlankProperties(source));
	}

	/**
	 *
	 * 将source中null或者空的字段取出加入忽略队列，把source复制到target并且忽略这些字段
	 * 
	 * @param source
	 * @param target
	 */
	public static void copyNotBlankProperties(Object source, Object target) {
		BeanUtils.copyProperties(source, target, getBlankProperties(source));
	}

	/**
	 *
	 * 将source中与target相同的字段取出加入忽略队列，把source复制到target并且忽略相同的字段
	 * 
	 * @param source
	 * @param target
	 */
	public static void copyDifferentProperties(Object source, Object target) {
		BeanUtils.copyProperties(source, target, getDifferentProperties(source, target));
	}

	/**
	 *
	 * 将source中与targetVo不同的字段取出加入忽略队列，把source复制到target并且这些字段
	 * 
	 * @param source
	 * @param target
	 */
	public static void copySameNamePropertiesByTargetVo(Object source, Object target, Object targetVo) {
		BeanUtils.copyProperties(source, target, getSameNameProperties(targetVo, source));
	}

	/**
	 *
	 * @param source
	 *            源数据
	 * @return 将源中为null的字段取出
	 */
	private static String[] getNullProperties(Object source) {

		BeanWrapper srcBean = new BeanWrapperImpl(source);
		PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
		Set<String> noEmptyName = new HashSet<>();
		for (PropertyDescriptor p : pds) {
			Object value = srcBean.getPropertyValue(p.getName());
			if (value == null) {
				noEmptyName.add(p.getName());
			}
		}
		String[] result = new String[noEmptyName.size()];
		return noEmptyName.toArray(result);
	}

	/**
	 * @param source
	 *            源数据
	 * @return 将源中不为null的字段取出
	 */
	private static String[] getNoNullProperties(Object source) {

		BeanWrapper srcBean = new BeanWrapperImpl(source);
		PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
		Set<String> noEmptyName = new HashSet<>();
		for (PropertyDescriptor p : pds) {
			Object value = srcBean.getPropertyValue(p.getName());
			if (value != null) {
				noEmptyName.add(p.getName());
			}
		}
		String[] result = new String[noEmptyName.size()];
		return noEmptyName.toArray(result);
	}

	/**
	 * @param source
	 *            源数据
	 * @return 将源中不为null或者空的字段取出
	 */
	private static String[] getNotBlankProperties(Object source) {

		BeanWrapper srcBean = new BeanWrapperImpl(source);
		PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
		Set<String> noEmptyName = new HashSet<>();
		for (PropertyDescriptor p : pds) {
			Object value = srcBean.getPropertyValue(p.getName());
			if (value != null && value != "") {
				noEmptyName.add(p.getName());
			}
		}
		String[] result = new String[noEmptyName.size()];
		return noEmptyName.toArray(result);
	}

	/**
	 * @param source
	 *            源数据
	 * @return 将源为null或者空的字段取出
	 */
	private static String[] getBlankProperties(Object source) {

		BeanWrapper srcBean = new BeanWrapperImpl(source);
		PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
		Set<String> noEmptyName = new HashSet<>();
		for (PropertyDescriptor p : pds) {
			Object value = srcBean.getPropertyValue(p.getName());
			if (value == null || value == "") {
				noEmptyName.add(p.getName());
			}
		}
		String[] result = new String[noEmptyName.size()];
		return noEmptyName.toArray(result);
	}

	/**
	 * @param source
	 *            源数据
	 * @return 将source与target中相同的字段取出
	 */
	private static String[] getDifferentProperties(Object source, Object target) {
		BeanWrapper sourceSrcBean = new BeanWrapperImpl(source);
		BeanWrapper targetSrcBean = new BeanWrapperImpl(target);

		PropertyDescriptor[] pds = targetSrcBean.getPropertyDescriptors();
		Set<String> noEmptyName = new HashSet<>();
		for (PropertyDescriptor p : pds) {
			if(sourceSrcBean.isReadableProperty(p.getName())){
				Object sourceValue = sourceSrcBean.getPropertyValue(p.getName());
				Object targetValue = targetSrcBean.getPropertyValue(p.getName());
				if (targetValue != null && targetValue.equals(sourceValue)) {
					noEmptyName.add(p.getName());
				}
			}
		}
		String[] result = new String[noEmptyName.size()];
		return noEmptyName.toArray(result);
	}

	/**
	 * @param source
	 *            源数据
	 * @return 将source与target中相同的字段取出
	 */
	private static String[] getSameNameProperties(Object source, Object target) {
		BeanWrapper sourceSrcBean = new BeanWrapperImpl(source);
		BeanWrapper targetSrcBean = new BeanWrapperImpl(target);

		PropertyDescriptor[] spds = sourceSrcBean.getPropertyDescriptors();
		PropertyDescriptor[] tpds = targetSrcBean.getPropertyDescriptors();
		Set<String> noEmptyName = new HashSet<>();
		Map<String, Object> tpdsMap = new HashMap<>();
		for (PropertyDescriptor p : tpds) {
			tpdsMap.put(p.getName(), targetSrcBean.getPropertyValue(p.getName()));
		}
		for (PropertyDescriptor spd : spds) {
			if (tpdsMap.containsKey(spd.getName())) {
				tpdsMap.remove(spd.getName());
			}
		}
		for (String s : tpdsMap.keySet()) {
			noEmptyName.add(s);
		}
		String[] result = new String[noEmptyName.size()];
		return noEmptyName.toArray(result);
	}

	/**
	 * bean 转换成 Map
	 * 
	 * @param object
	 * @return
	 * @throws IllegalAccessException
	 */
	public static Map beanToMap(Object object) throws IllegalAccessException {
		Map<String, Object> reMap = new HashMap<String, Object>();
		if (object == null) {
			return null;
		}

		Field[] fields = object.getClass().getDeclaredFields();
		try {
			for (Field field : fields) {
				try {
					Field f = object.getClass().getDeclaredField(field.getName());
					f.setAccessible(true);
					Object o = f.get(object);
					reMap.put(field.getName(), o);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		}

		return reMap;
	}

	/**
	 * @param map
	 * @param beanClass
	 *            需要的bean类型
	 * @param <T>
	 * @return
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	public static <T extends BaseModel> T mapToBean(Map map, Class<T> beanClass) throws IllegalAccessException, InstantiationException {
		T object = beanClass.newInstance();

		Field[] fields = object.getClass().getDeclaredFields();
		for (Field field : fields) {
			int mod = field.getModifiers();
			if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
				continue;
			}
			field.setAccessible(true);
			if (map.containsKey((field.getName()))) {
				field.set(object, map.get(field.getName()));
			}
		}
		Field[] fields2 = object.getClass().getSuperclass().getDeclaredFields();
		for (Field field : fields2) {
			int mod = field.getModifiers();
			if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
				continue;
			}
			field.setAccessible(true);
			if (map.containsKey((field.getName()))) {
				field.set(object, map.get(field.getName()));
			}
		}
		return object;
	}

	public static List<Integer> stringConverterToIntegerList(String str){
		int[] ints = Arrays.stream( str.split(",")).mapToInt(Integer::parseInt).toArray();
		return Arrays.stream(ints).boxed().collect(Collectors.toList());
	}
}
